package com.fingard.dsp.bank.directbank.gxnx02;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.crypto.DigestHelper;
import com.fingard.db.JDBCHelper;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.IBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.detail.RetAtsBatPayRecDetail;
import com.fingard.io.FileHelper;
import com.fingard.net.ConnState;
import com.fingard.text.MFSHelper;
import com.fingard.text.StringHelper;
import com.fingard.util.SmbFileUtil;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import java.io.File;
import java.sql.Connection;
import java.util.*;

import static com.fingard.text.StringHelper.trimEndFileSp;

/**
 * @author Alon on 2019-10-25.
 * @version 1.0
 */
public class GXNX02BatPayRec extends GXNX02Base implements IBatPayRec {
    private static final String INSERTRECEIPT = "INSERT INTO REQSEQIDMAPPING(URID,BANKCODE,TRANSDATE,REQSEQID,BANKREQSEQID,RESERVE1) values (?,?,?,?,?,?);";
    private static final String SELECTRECEIPT = "SELECT BANKREQSEQID,TRANSDATE,RESERVE1 FROM REQSEQIDMAPPING WHERE REQSEQID=? and BANKCODE=?;";

    /**
     * @param p_req1988 批量代付
     * @return
     * @throws Exception
     */
    @Override
    public RetAtsBatPayRec d_1988_BatPay(ReqBatPayRec p_req1988) throws Exception {
        RetAtsBatPayRec retAts = new RetAtsBatPayRec(p_req1988.reqHeader);
        Connection conn = FGBiz.getLocalDbConn();
        try {
            /**
             *1.组装明细文件，上传文件
             */
            String BatchDate = Format.Date8Format.format(new Date());//批次请求日期 YYYYMMDD
            String BatchNo = bankFront.operator + getID();//批次号：4位企业代码+2位序列
            String fileName = "DF" + BatchDate + BatchNo + ".REQ";
            //本地路径
            String filePath = getTempFileDirectory() + File.separator + "uploads" + File.separator + fileName;
            //组装明细文件内容
            Map<String, Object> resultAndfileContext = new HashMap<String, Object>();
            resultAndfileContext = writerPayFileContext(p_req1988);
            if ("false".equals(resultAndfileContext.get("result"))) {
                retAts.respCode = "-1";
                retAts.respInfo = "总笔数与循环数不一致";
                retAts.reqSeqID = p_req1988.reqBatchNO;
                retAts.writeRetToATS();
                return retAts;
            }
            WriteBankLogLn2("批次明细序号映射文件路径: " + filePath);
            WriteBankLogLn("交易信息文件内容:" + resultAndfileContext.get("fileContext").toString());
            //将文件内容写入到本地磁盘中
            FileHelper.writeFile(filePath, resultAndfileContext.get("fileContext").toString(), getCharset2());
            WriteBankLogLn(p_req1988.reqBatchNO + "批号代付文件处理完毕,一共" + p_req1988.getTotalNum() + "条明细.");

            //上传到前置机指定目录下
            WriteBankLogLn("开始上传文件至共享文件夹...");
            WriteBankLogLn("前置机共享文件夹目录：" + trimEndFileSp(bankFront.bkTransFolder));
            //上传文件到前置机目录
            if (FileHelper.existFile(filePath)) {
                String remotePath = trimEndFileSp(bankFront.bkTransFolder) + "/";
                int result = SmbFileUtil.smbUploading(filePath, "", remotePath);
                if (result == -1) {
                    retAts.respCode = "-1";
                    retAts.respInfo = "上传文件到前置机目录异常";
                    retAts.writeRetToATS();
                    return retAts;
                } else if (result == 1) {
                    retAts.respCode = "-1";
                    retAts.respInfo = "文件已存在共享目录无需重复上传";
                    retAts.writeRetToATS();
                }
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = "批付文件不存在";
                retAts.writeRetToATS();
                return retAts;
            }

            /**
             * 2.组装报文，发送给银行
             */
            XmlTextWriter xmlTextWriter = new XmlTextWriter();
            GXNX02Header header = new GXNX02Header();
            header.tranCode = "3001S";
            header.tranSeq = Format.DateTime14Format.format(new Date()) + bankFront.operator
                    + header.tranCode.substring(0, 4) + getQryTransID();
            writeCommonHeader1(xmlTextWriter, header);
            xmlTextWriter.writeStartElement("REQBODY");
            xmlTextWriter.writeElementString("BatchDate", BatchDate);
            xmlTextWriter.writeElementString("BatchNo", BatchNo);
            //存入批次号，交易日期，本地批量文件名(含路径)，用于批量查询
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            JDBCHelper.update(conn, INSERTRECEIPT, new Object[]{uuid, p_req1988.reqHeader.bankCode, BatchDate, p_req1988.reqBatchNO, BatchNo, filePath});
            xmlTextWriter.writeElementString("AcctNo", p_req1988.ownAct);
            xmlTextWriter.writeElementString("HZAcctNo", "", true);//划转账号
            xmlTextWriter.writeElementString("FileName", fileName);
            xmlTextWriter.writeElementString("Count", p_req1988.totalNum);
            xmlTextWriter.writeElementString("Amt", p_req1988.totalAmt);
//            String p_filepath = getTempFileDirectory() + File.separator + "uploads" + File.separator + fileName;//用本地文件测试
            String p_filepath = StringHelper.trimEnd(bankFront.bkPayFolder, File.separator) + File.separator + fileName;
            byte[] fileMd5 = DigestHelper.cryptoMD5FromFile(p_filepath);
            xmlTextWriter.writeElementString("MD5", DigestHelper.cryptoMD5RetHexStr(fileMd5));
            xmlTextWriter.writeEndDocument();

            String[] tmpStrRet = sendToBank1(xmlTextWriter.toXmlString());
            /**
             *  3.接收银行返回报文，解析返回ATS
             */
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                //解析银行返回
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpRespCode = tmpBkReader.getFirstText("/GXNXYQ/RESP/RESPHEAD/RspCode");
                    String tmpRetInfo = tmpBkReader.getFirstText("/GXNXYQ/RESP/RESPHEAD/RspMsg");
                    if ("000000".equals(tmpRespCode)) {
                        retAts.respCode = "0";
                        retAts.respInfo = tmpRetInfo;
                        retAts.reqSeqID = p_req1988.reqBatchNO;
                        retAts.transState = tmpRespCode;
                        retAts.payInfoCode = tmpRespCode;
                    } else if ("AUTHRQ".equals(tmpRespCode)) {
                        retAts.respCode = "0";
                        retAts.reqSeqID = p_req1988.reqBatchNO;
                        retAts.respInfo = "需要落地，需致电柜员授权后查询交易结果";
                        retAts.transState = tmpRespCode;
                        retAts.payInfoCode = tmpRespCode;
                    } else {
                        retAts.respCode = "0";
                        retAts.respInfo = tmpRetInfo;
                        retAts.reqSeqID = p_req1988.reqBatchNO;
                        retAts.transState = tmpRespCode;
                        retAts.payInfoCode = tmpRespCode;
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = tmpSbMsg.toString();
                }
            } else if (tmpStrRet[0].equals(ConnState.FAIL)) {
                retAts.respCode = "0";
                retAts.respInfo = tmpStrRet[1];
                retAts.reqSeqID = p_req1988.reqBatchNO;
                retAts.transState = PaymentState.FAIL_Batch;
                retAts.payInfoCode = tmpStrRet[0];
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = tmpStrRet[1];
            }

        } catch (Exception e) {
            retAts.respCode = "-1";
            retAts.respInfo = e.toString();
            e.printStackTrace();
        } finally {
            conn.close();
        }
        retAts.writeRetToATS();
        return retAts;
    }

    /**
     * @param p_req1998 批量代付查询
     * @return
     * @throws Exception
     */
    @Override
    public RetAtsQryBatPayRec d_1998_QryBatPay(ReqQryBatPayRec p_req1998) throws Exception {
        RetAtsQryBatPayRec retAts = new RetAtsQryBatPayRec(p_req1998.reqHeader);
        Connection conn = FGBiz.getLocalDbConn();
        RetAtsBatPayRecDetail tmpRecDetail = new RetAtsBatPayRecDetail();
        try {
            Map<String, Object> map = JDBCHelper.execQuerySingle(conn, SELECTRECEIPT, new Object[]{p_req1998.reqBatchNO, p_req1998.reqHeader.bankCode});
            if (map.size() == 0) {
                retAts.respCode = "-1";
                retAts.respInfo = "数据库流水号映射异常！";
                retAts.writeAfterDetail();
                return retAts;
            }
            String tmpLocalMarkPath = map.get("RESERVE1").toString();//本地明细映射文件名(含路径)
            WriteBankLogLn2("批次流水映射文件路径: " + tmpLocalMarkPath);
            File localMarkFile = new File(tmpLocalMarkPath);
            if (!localMarkFile.exists()) {
                retAts.respCode = "-1";
                retAts.respInfo = "批次流水映射文件未生成,未发生交易!";
                retAts.writeAfterDetail();
                return retAts;
            }
            String tmpSeqIDData = FileHelper.readToString(localMarkFile, getCharset2());//本地明细文件内容
            WriteBankLogLn2("本地流水映射文件内容:" + tmpSeqIDData);
            if (StringHelper.isNullOrEmpty(tmpSeqIDData)) {
                retAts.respCode = "-1";
                retAts.respInfo = "批次流水映射文件内容为空,未发生交易!";
                retAts.writeAfterDetail();
                return retAts;
            }

            XmlTextWriter xmlTextWriter = new XmlTextWriter();
            GXNX02Header header = new GXNX02Header();
            header.tranCode = "3002S";
            header.tranSeq = Format.DateTime14Format.format(new Date()) + bankFront.operator
                    + header.tranCode.substring(0, 4) + getQryTransID();
            writeCommonHeader1(xmlTextWriter, header);
            xmlTextWriter.writeStartElement("REQBODY");
            xmlTextWriter.writeElementString("BatchDate", map.get("TRANSDATE").toString());
            xmlTextWriter.writeElementString("BatchNo", map.get("BANKREQSEQID").toString());
            xmlTextWriter.writeEndElement();
            xmlTextWriter.writeEndDocument();

            String[] tmpStrRet = sendToBank1(xmlTextWriter.toXmlString());

            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpRespCode = tmpBkReader.getFirstText("/GXNXYQ/RESP/RESPHEAD/RspCode");
                    String tmpRetInfo = tmpBkReader.getFirstText("/GXNXYQ/RESP/RESPHEAD/RspMsg");
                    if ("000000".equals(tmpRespCode)) {
                        String stat = tmpBkReader.getFirstText("/GXNXYQ/RESP/RESPBODY/BthCode");
                        String statInfo = tmpBkReader.getFirstText("/GXNXYQ/RESP/RESPBODY/BthMsg");
                        retAts.respCode = "0";
                        retAts.reqSeqID = p_req1998.reqHeader.reqSeqID;
                        retAts.respInfo = tmpRetInfo;
                        StringHelper.joinNotEmpty(",", tmpRetInfo, statInfo);
                        if ("000000".equals(stat)) {//交易处理成功，去获取交易结果明细文件内容，查询单笔支付状态
                            String tmpBatchFileName = tmpBkReader.getFirstText("/GXNXYQ/RESP/RESPBODY/HPFile");
                            //去前置机获取批量支付存入的文件
                            String tmpResultData = null;//读取的数据
                            //下载共享目录批量查询文件
                            String downloadFilePath = trimEndFileSp(bankFront.bkTransFolder) + File.separator;//共享目录路径
                            String p_FileFullPath = getTempFileDirectory() + File.separator + Format.Time6Format.format(new Date());//下载到的本地路径
                            StringBuilder p_sb = new StringBuilder();
                            if (SmbFileUtil.smbDownload(p_FileFullPath, downloadFilePath, tmpBatchFileName, p_sb) == 1) {
                                p_FileFullPath = p_FileFullPath + File.separator + tmpBatchFileName;
                                WriteBankLogLn("文件下载成功，位于：" + p_FileFullPath);
                                tmpResultData = FileHelper.readFileText(p_FileFullPath, getCharset2());
                            } else {
                                retAts.writeRespCode("-1");
                                retAts.writeRespInfo(p_sb.toString());
                                retAts.writeEnd();
                                return retAts;
                            }

                            if (tmpResultData == null) {
                                this.WriteBankLogLn("读取前置数据文件返回为null，需确认前置文件夹配置和文件是否存在");
                            } else {
                                this.WriteBankLogStep3(tmpResultData);
                            }

                            WriteBankLogLn("银行查询文件返回内容为：" + tmpResultData);

                            String[] tmpResultDataArrary = tmpResultData.split("\n", 2);
                            StringBuilder tmpSbLog = new StringBuilder();
                            ArrayList<String[]> tmpArrayList = MFSHelper.getTextArray(tmpResultDataArrary[1], "|", 9, -1, tmpSbLog);
                            if (tmpSbLog.length() == 0) {
                                WriteBankLogLn("返回的记录条数：" + tmpArrayList.size());

                                for (int i = 0; i < tmpArrayList.size(); i++) {
                                    // 0业务流水号| 1银行账号| 2户名| 3入账金额| 4入账日期| 5入账流水号| 6处理结果| 7处理结果说明| 8账务机构|
                                    String[] tmpEachArr = tmpArrayList.get(i);
                                    WriteBankLogLn("返回的记录长度：" + tmpEachArr.length);
                                    WriteBankLogLn("返回的记录内容：" + Arrays.toString(tmpEachArr));
                                    RetAtsBatPayRecDetail tmpRetDetail = new RetAtsBatPayRecDetail();

                                    if (tmpEachArr[3].equals("0")) {//银行接口文档：如果记账失败则记账为0（参考：ATSES-16755 广西农信银企直联平台接口规范V2.7(20190220(1).doc 第30页）
                                        tmpRetDetail.result = "failure";
                                    } else {
                                        tmpRetDetail.result = tmpEachArr[6];
                                    }
                                    tmpRetDetail.recAct = tmpEachArr[1];//收款账号
                                    tmpRetDetail.recName = tmpEachArr[2];//收款名
                                    tmpRecDetail.payAmount = tmpEachArr[3];//银行记账金额(实际交易金额)
                                    tmpRecDetail.payAct = p_req1998.reqHeader.ownAct;//付款账号
                                    tmpRetDetail.payInfoCode = tmpRetDetail.result;
                                    tmpRetDetail.memo = tmpEachArr[7];//处理结果说明
                                    tmpRecDetail.postScript = tmpEachArr[0];//对账码
                                    retAts.writeRetDetail(tmpRetDetail);
                                }
                            } else {
                                retAts.respCode = "-1";
                                retAts.respInfo = tmpSbLog.toString();
                            }
                        } else {//stat：888999交易处理中  999999交易未建立...
                            retAts.respCode = "0";
                            retAts.reqSeqID = p_req1998.reqHeader.reqSeqID;
                            retAts.respInfo = tmpRetInfo;
                            retAts.transState = stat;
                            retAts.payInfoCode = stat;
                            //解析本地映射文件内容，得到对账码
                            String[] tmpResultDataArrary = tmpSeqIDData.split("\n", 2);
                            StringBuilder tmpSbLog = new StringBuilder();
                            ArrayList<String[]> tmpArrayList = MFSHelper.getTextArray(tmpResultDataArrary[1], "|", 7, -1, tmpSbLog);
                            if (tmpSbLog.length() == 0) {
                                for (int i = 0; i < tmpArrayList.size(); i++) {
                                    String[] tmpEachArr = tmpArrayList.get(i);
                                    RetAtsBatPayRecDetail tmpRetDetail = new RetAtsBatPayRecDetail();

                                    tmpRetDetail.result = stat;
                                    tmpRetDetail.payInfoCode = stat;
                                    tmpRecDetail.postScript = tmpEachArr[0];//对账码

                                    retAts.writeRetDetail(tmpRetDetail);
                                }
                            } else {
                                retAts.respCode = "-1";
                                retAts.respInfo = tmpSbLog.toString();
                            }
                        }
                    } else if ("AUTHRQ".equals(tmpRespCode)) {
                        retAts.respCode = "0";
                        retAts.reqSeqID = p_req1998.reqHeader.reqSeqID;
                        retAts.respInfo = "需要落地，需致电柜员授权后查询交易结果";
                        retAts.transState = tmpRespCode;
                        retAts.payInfoCode = tmpRespCode;
                    } else {
                        retAts.respCode = "-1";
                        retAts.reqSeqID = p_req1998.reqHeader.reqSeqID;
                        retAts.respInfo = tmpRetInfo;
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.reqSeqID = p_req1998.reqHeader.reqSeqID;
                    retAts.respInfo = tmpSbMsg.toString();
                }
            } else {
                retAts.respCode = "-1";
                retAts.reqSeqID = p_req1998.reqHeader.reqSeqID;
                retAts.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            retAts.respCode = "-1";
            retAts.reqSeqID = p_req1998.reqHeader.reqSeqID;
            retAts.respInfo = e.getMessage();
            e.printStackTrace();
        }

        retAts.writeAfterDetail();
        return retAts;
    }

    @Override
    public RetAtsBatPayRec d_9188_BatPay(ReqBatPayRec p_req9188) throws Exception {
        return null;
    }

    @Override
    public RetAtsQryBatPayRec d_9198_QryBatPay(ReqQryBatPayRec p_req9198) throws Exception {
        return null;
    }
}
